﻿using Basic.HrCollect;
using Basic.HrModel.Emp;
using Basic.HrRemoteModel.Emp.Model;
using Basic.HrService.Interface;
using Basic.HrService.Model;
using WeDonekRpc.Helper;

namespace Basic.HrService.lmpl
{
    internal class EmpSearchService : IEmpSearchService
    {
        private readonly IEmpCollect _Service;
        private readonly ICompanyCollect _Company;
        private readonly IDeptCollect _Dept;
        public EmpSearchService ( IEmpCollect service,
            ICompanyCollect company,
            IDeptCollect dept )
        {
            this._Service = service;
            this._Company = company;
            this._Dept = dept;
        }
        public WhileEmpResult Search ( WhileFilterParam param )
        {
            UIDeptDto dept = this._Dept.Get<UIDeptDto>(param.CurDeptId);
            if ( param.IsLeader )
            {
                return this._GetLeader(dept, param.Range);
            }
            else
            {
                EmpSearchArg arg = new EmpSearchArg
                {
                    CompanyId = param.CompanyId,
                    Title = param.Title,
                    Post = param.Post,
                };
                return this._Search(dept, arg, param.Range);
            }
        }
        private WhileEmpResult _Search ( UIDeptDto dept, EmpSearchArg arg, FilterRange range )
        {
            if ( dept.ParentId == 0 && dept.IsUnit )
            {
                return null;
            }
            long deptId;
            if ( range == FilterRange.单位 )
            {
                deptId = dept.IsUnit ? dept.ParentId : dept.UnitId;
                arg.UnitId = [deptId];
            }
            else if ( dept.IsUnit || dept.ParentId == dept.UnitId )
            {
                return null;
            }
            else
            {
                deptId = dept.ParentId;
                arg.DeptId = [deptId];
            }
            long[] empId = this._Service.SearchById(arg);
            if ( !empId.IsNull() )
            {
                return new WhileEmpResult
                {
                    NextDeptId = deptId == 0 ? null : deptId,
                    EmpId = empId
                };
            }
            dept = this._Dept.Get<UIDeptDto>(deptId);
            if ( dept.ParentId == 0 )
            {
                return null;
            }
            return this._Search(dept, arg, range);
        }

        private WhileEmpResult _GetLeader ( UIDeptDto dept, FilterRange range )
        {
            if ( range == FilterRange.部门单位 )
            {
                if ( dept.LeaderId.HasValue )
                {
                    return new WhileEmpResult
                    {
                        EmpId = new long[] { dept.LeaderId.Value },
                        NextDeptId = dept.ParentId == 0 ? null : dept.ParentId,
                    };
                }
                else if ( dept.ParentId == 0 )
                {
                    return null;
                }
                long deptId = dept.ParentId;
                long? empId = this._GetLeaderId(deptId, out long? next);
                if ( empId.HasValue )
                {
                    return new WhileEmpResult
                    {
                        EmpId = new long[] { empId.Value },
                        NextDeptId = next
                    };
                }
            }
            else if ( range == FilterRange.单位 )
            {
                if ( dept.LeaderId.HasValue && dept.IsUnit )
                {
                    return new WhileEmpResult
                    {
                        EmpId = new long[] { dept.LeaderId.Value },
                        NextDeptId = dept.ParentId == 0 ? null : dept.ParentId
                    };
                }
                else if ( dept.ParentId == 0 && dept.IsUnit )
                {
                    return null;
                }
                long deptId = dept.IsUnit ? dept.ParentId : dept.UnitId;
                long? empId = this._GetLeaderId(deptId, out long? next);
                if ( empId.HasValue )
                {
                    return new WhileEmpResult
                    {
                        EmpId = new long[] { empId.Value },
                        NextDeptId = next
                    };
                }
            }
            else if ( dept.IsUnit )
            {
                return null;
            }
            else
            {
                if ( dept.LeaderId.HasValue )
                {
                    return new WhileEmpResult
                    {
                        EmpId = new long[] { dept.LeaderId.Value },
                        NextDeptId = dept.ParentId == 0 ? null : dept.ParentId
                    };
                }
                else if ( dept.ParentId == 0 )
                {
                    return null;
                }
                long deptId = dept.ParentId;
                long? empId = this._GetLeaderId(deptId, out long? next, true);
                if ( empId.HasValue )
                {
                    return new WhileEmpResult
                    {
                        EmpId = new long[] { empId.Value },
                        NextDeptId = next
                    };
                }
            }
            return null;
        }
        private long? _GetLeaderId ( long deptId, out long? nextDeptId, bool excludeUnit = false )
        {
            UIDeptDto prt = this._Dept.Get<UIDeptDto>(deptId);
            if ( excludeUnit && prt.IsUnit )
            {
                nextDeptId = null;
                return null;
            }
            if ( prt.LeaderId.HasValue )
            {
                nextDeptId = prt.ParentId == 0 ? null : prt.ParentId;
                return prt.LeaderId;
            }
            else if ( prt.ParentId == 0 )
            {
                nextDeptId = null;
                return null;
            }
            deptId = prt.ParentId;
            return this._GetLeaderId(deptId, out nextDeptId, excludeUnit);
        }
        public SearchEmpResult SearchEmp ( EmpSearchParam param, int take, int index )
        {
            EmpSearchArg query = new EmpSearchArg
            {
                CompanyId = param.CompanyId,
                Title = param.Title,
                Post = param.Post,
            };
            if ( param.DeptId.HasValue )
            {
                if ( param.Change == SearchRange.当前 )
                {
                    query.DeptId = new long[] { param.DeptId.Value };
                }
                else if ( param.Change == SearchRange.上级 )
                {
                    query.DeptId = [this._Dept.GetParentId(param.DeptId.Value)];
                }
                else if ( param.Change == SearchRange.下级 )
                {
                    query.DeptId = this._Dept.GetSubDeptId(param.DeptId.Value);
                }
            }
            else if ( param.UnitId.HasValue )
            {
                if ( param.Change == SearchRange.当前 )
                {
                    query.UnitId = new long[] { param.UnitId.Value };
                }
                else if ( param.Change == SearchRange.上级 )
                {
                    query.UnitId = [this._Dept.GetParentId(param.UnitId.Value)];
                }
                else if ( param.Change == SearchRange.下级 )
                {
                    query.UnitId = this._Dept.GetSubUnitId(param.UnitId.Value);
                }
            }
            long[] empId = null;
            int count = 0;
            if ( param.IsLeader )
            {
                if ( !query.DeptId.IsNull() )
                {
                    empId = this._Dept.GetLeaderId(query.DeptId);
                    count = empId.Length;
                }
                else if ( !query.UnitId.IsNull() )
                {
                    empId = this._Dept.GetLeaderId(query.UnitId);
                    count = empId.Length;
                }
                else
                {
                    long? id = this._Company.GetLeaderId(param.CompanyId);
                    if ( id.HasValue )
                    {
                        empId = [id.Value];
                        count = 1;
                    }
                }
            }
            else
            {
                empId = this._Service.SearchById(query, take, index, out count);
            }
            return new SearchEmpResult
            {
                Count = count,
                EmpId = empId,
                FilterParam = new SearchFilterParam
                {
                    CompanyId = param.CompanyId,
                    DeptId = query.DeptId,
                    Post = query.Post,
                    Title = query.Title,
                    UnitId = query.UnitId,
                    IsLeader = param.IsLeader,
                }
            };
        }
    }
}
